package robato.ui;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Component;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.FlowLayout;
import java.awt.Dimension;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import org.jfree.ui.RefineryUtilities;
import org.eclipse.wb.swing.FocusTraversalOnArray;
import javax.swing.border.TitledBorder;
import javax.swing.filechooser.FileNameExtensionFilter;

import robato.util.CaptureScreen;
import robato.logic.Robot;
import robato.logic.Training;

public class GUIRobots extends JFrame implements ActionListener, Observer {
	
	private static final long serialVersionUID = 5984342963665257697L;
	
	int intNumComunicaciones = 0;
	int intTotalMensajes = 0;
	int intTotalAciertos = 0;
	int intNumRobots = 0;
	int intIteraciones = 0;
	double dblAprendizaje = 0;
	boolean blnParar = true;

	Training training;
	Thread hilo;
	Robot robots[];
	Grafico grafico;
	CaptureScreen captureScreen;
	FrameMatriz frameMatrices;
	String arrSimbolos[];
	String arrSignificados[];
	String strDirectorio = "c://robots/";
	Vector<int[]> vectorParejas ;
	
	JFileChooser fc;
	JTextField textNRobots;
	JTextField textAprendizaje;
	JTextField textIteraciones;
	JTextArea textArea;
	JButton btnEntrenar;
	JComboBox selectMetodo;
	JPanel panelGrafico;
	JPanel panelOpciones;
	JPanel panelCentral;
	JScrollPane scrollPane;
	JPanel panel_1;
	JPanel panelBotones;
	JLabel lblMatrizRobot;
	JComboBox comboBoxMatriz;
	JButton btnVerMatriz;
	JPanel panel_4;
	JButton btnGuardar;
	JButton btnCargar;
	JButton btnInit;
	JButton btnPausa;

	GUIRobots() {
		setMinimumSize(new Dimension(1024, 500));
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setTitle("Robots Autonomos");
		getContentPane().setLayout(new BorderLayout(5, 5));

		JPanel panel = new JPanel();
		panel.setAutoscrolls(true);
		getContentPane().add(panel);
		panel.setLayout(new BorderLayout(5, 5));

		panelOpciones = new JPanel();
		panelOpciones.setBorder(new TitledBorder(null, "Opciones", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		panel.add(panelOpciones, BorderLayout.NORTH);
		panelOpciones.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

		JLabel lblNRobots = new JLabel("N\u00BA Robots");
		panelOpciones.add(lblNRobots);

		textNRobots = new JTextField();
		textNRobots.setText("16");
		panelOpciones.add(textNRobots);
		textNRobots.setColumns(10);

		JLabel lblLabel = new JLabel("Aprendizaje");
		panelOpciones.add(lblLabel);

		textAprendizaje = new JTextField();
		textAprendizaje.setText("0.03");
		panelOpciones.add(textAprendizaje);
		textAprendizaje.setColumns(10);

		JLabel lblNewLabel_1 = new JLabel("N\u00BA Iteraciones");
		panelOpciones.add(lblNewLabel_1);

		textIteraciones = new JTextField();
		textIteraciones.setText("100");
		panelOpciones.add(textIteraciones);
		textIteraciones.setColumns(10);

		JLabel lblMetodo = new JLabel("Metodo:");
		lblMetodo.setAlignmentX(Component.CENTER_ALIGNMENT);
		panelOpciones.add(lblMetodo);

		selectMetodo = new JComboBox();
		selectMetodo.setModel(new DefaultComboBoxModel(new String[] { "Aleatorio", "Quorum" }));
		selectMetodo.setMaximumRowCount(5);
		panelOpciones.add(selectMetodo);
		panelOpciones.setFocusTraversalPolicy(new FocusTraversalOnArray(
				new Component[] { textNRobots, textAprendizaje, textIteraciones, selectMetodo }));

		panelCentral = new JPanel();
		panel.add(panelCentral, BorderLayout.CENTER);
		panelCentral.setLayout(new GridLayout(0, 2, 0, 0));

		panelGrafico = new JPanel();
		panelCentral.add(panelGrafico);
		panelGrafico.setLayout(new BorderLayout(0, 0));

		scrollPane = new JScrollPane();
		scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
		scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
		panelCentral.add(scrollPane);

		textArea = new JTextArea();
		scrollPane.setViewportView(textArea);

		JPanel panel_3 = new JPanel();
		panel.add(panel_3, BorderLayout.SOUTH);
		panel_3.setLayout(new GridLayout(0, 3, 0, 0));

		panel_1 = new JPanel();
		panel_1.setBorder(new TitledBorder(null, "Ver Matrices", TitledBorder.LEADING, TitledBorder.TOP, null, null));
		panel_3.add(panel_1);

		lblMatrizRobot = new JLabel("Robot:");
		panel_1.add(lblMatrizRobot);

		comboBoxMatriz = new JComboBox();
		panel_1.add(comboBoxMatriz);

		btnVerMatriz = new JButton("Ver");
		btnVerMatriz.addActionListener(this);
		btnVerMatriz.setEnabled(false);
		panel_1.add(btnVerMatriz);

		panelBotones = new JPanel();
		FlowLayout flowLayout = (FlowLayout) panelBotones.getLayout();
		flowLayout.setVgap(15);
		panel_3.add(panelBotones);

		btnInit = new JButton("Inicializar");
		btnInit.addActionListener(this);
		panelBotones.add(btnInit);

		btnEntrenar = new JButton("Entrenar");
		btnEntrenar.addActionListener(this);
		btnEntrenar.setEnabled(false);
		panelBotones.add(btnEntrenar);
		
		
		btnPausa = new JButton("Pausa");
		btnPausa.addActionListener(this);
		btnPausa.setEnabled(false);
		panelBotones.add(btnPausa);

		panel_4 = new JPanel();
		FlowLayout flowLayout_1 = (FlowLayout) panel_4.getLayout();
		flowLayout_1.setVgap(15);
		panel_3.add(panel_4);

		btnCargar = new JButton("Cargar");
		btnCargar.addActionListener(this);
		panel_4.add(btnCargar);

		btnGuardar = new JButton("Guardar");
		btnGuardar.addActionListener(this);
		btnGuardar.setEnabled(false);
		panel_4.add(btnGuardar);

		this.fc = new JFileChooser();
		this.fc.addChoosableFileFilter(new FileNameExtensionFilter("Robot Autonomos", "robato"));
		this.fc.setCurrentDirectory(new File(this.strDirectorio));
		
		this.frameMatrices = new FrameMatriz();
		this.frameMatrices.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
		
		this.grafico = new Grafico(this.strDirectorio);
		this.panelGrafico.add(this.grafico, BorderLayout.CENTER);
			
		this.pack();
	}

	public void fillcomboBoxMatriz() {
		this.comboBoxMatriz.removeAllItems();
		this.comboBoxMatriz.addItem("Todos..");
		for (int i = 1; i <= this.intNumRobots; i++) {
			this.comboBoxMatriz.addItem("ROBOT-" + i);
		}
	}
	
	public void initParametros(Robot robots[], int intNumRobots, String arrSymbols[], String arrMeanings[], double dblAprendizaje) {
		this.robots = robots;
		this.intNumRobots = intNumRobots;
		this.arrSimbolos = arrSymbols;
		this.arrSignificados = arrMeanings;
		this.dblAprendizaje = dblAprendizaje;
		
		if (this.robots == null) {
			this.robots = new Robot[this.intNumRobots];
			for (int i = 0; i < this.intNumRobots; i++) {
				this.robots[i] = new Robot(this.arrSimbolos, this.arrSignificados, this.dblAprendizaje);
				this.robots[i].setName("ROBOT-" + (i + 1));
			}
		}

		this.grafico.clearSeries();
		this.captureScreen = new CaptureScreen();
		this.training = new Training();
		this.training.addObserver(this);
		this.hilo=null;
		this.blnParar=true;
		this.textArea.setText("");
	}
	
	@SuppressWarnings("unchecked")
	public synchronized  void actionPerformed(ActionEvent e) {
		if (e.getSource().equals(this.btnInit)) {
			
			int intNumeroRobots = Integer.parseInt(textNRobots.getText().trim());
			double dblAprendiz = Double.parseDouble(textAprendizaje.getText().trim());
			
			if (intNumeroRobots <= 0) {
				intNumeroRobots = 5;
				this.textNRobots.setText("5");
			}
			if (dblAprendiz <= 0) {
				dblAprendiz = 0.3;
				this.textAprendizaje.setText("0.3");
			}
			
			String simbolos[] = new String[10];
			simbolos[0] = "MESA";
			simbolos[1] = "SILLA";
			simbolos[2] = "TV";
			simbolos[3] = "CAMA";
			simbolos[4] = "RADIO";
			simbolos[5] = "NEVERA";
			simbolos[6] = "ESTUFA";
			simbolos[7] = "CARRO";
			simbolos[8] = "JUGUETE";
			simbolos[9] = "ARMARIO";

			String significados[] = new String[10];
			significados[0] = "DO-RE";
			significados[1] = "DO-MI";
			significados[2] = "DO-FA";
			significados[3] = "DO-SOL";
			significados[4] = "DO-LA";
			significados[5] = "DO-SI";
			significados[6] = "RE-DO";
			significados[7] = "RE-MI";
			significados[8] = "RE-FA";
			significados[9] = "RE-SOL";
	
			this.initParametros(null, intNumeroRobots, simbolos, significados, dblAprendiz);
			this.fillcomboBoxMatriz();
			this.btnGuardar.setEnabled(true);
			this.btnEntrenar.setEnabled(true);
			this.btnVerMatriz.setEnabled(true);
			this.btnPausa.setEnabled(false);

			this.frameMatrices.setRobots(this.robots);
			if(this.frameMatrices.isVisible()){
				int index = this.comboBoxMatriz.getSelectedIndex() - 1;
				this.frameMatrices.printMatriz(index);
			}
		}

		else if (e.getSource().equals(this.btnEntrenar)) {
			String strSelected = (String) this.selectMetodo.getSelectedItem().toString().trim().toUpperCase();
			this.intIteraciones = Integer.parseInt(textIteraciones.getText().trim());			
			this.textArea.setText("Total Robots:"+this.robots.length+"   Aprendizaje: "+this.dblAprendizaje+"  Iteraciones: "+this.intIteraciones+"\n");
			
			this.training.setParameters(this.robots, this.intIteraciones, strSelected);
			this.hilo = new Thread(this.training,"Hilo: Entranamiento");
			this.hilo.start();
			
			this.btnPausa.setEnabled(true);
			this.btnEntrenar.setEnabled(false);
			this.btnInit.setEnabled(false);
		}
		else if(e.getSource().equals(this.btnPausa)) {
			//synchronized (this.training) {
				if(this.blnParar){
					this.training.setParar(true);
					this.btnInit.setEnabled(true);
				}
				else{
					this.training.setParar(false);
					this.btnInit.setEnabled(false);
				}
				this.blnParar = !this.blnParar;
			//}
		}

		else if (e.getSource().equals(this.btnVerMatriz)) {
			
			int index = this.comboBoxMatriz.getSelectedIndex() - 1;
			this.frameMatrices.printMatriz(index);
			this.frameMatrices.setVisible(true);
			
			if (index == -1){
				for(int i=0; i<this.robots.length; i++ )
					this.textArea.append("\nInformacion Robot:\n" + this.robots[i].toString());
			}
			else{
				this.textArea.append("\nInformacion Robot:\n" + this.robots[index].toString());
			}
		}

		else if (e.getSource().equals(this.btnCargar)) {
			int returnVal = this.fc.showOpenDialog(this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				try {
					String strFile = this.fc.getSelectedFile().getAbsolutePath();
					FileInputStream fis = new FileInputStream(new File(strFile));
					ObjectInputStream in = new ObjectInputStream(fis);
					this.robots = (Robot[]) in.readObject();
					this.vectorParejas = (Vector<int[]>) in.readObject();;
					in.close();

					this.arrSignificados = robots[0].arrMeanings;
					this.arrSimbolos = robots[0].arrSymbols;
					this.dblAprendizaje = robots[0].dblAprendizaje;
					this.intNumRobots = this.robots.length;
					this.textAprendizaje.setText("" + this.dblAprendizaje);
					this.textNRobots.setText("" + this.intNumRobots);
					
					this.initParametros(this.robots, this.intNumRobots, this.arrSimbolos, this.arrSignificados, this.dblAprendizaje);

					this.btnGuardar.setEnabled(true);
					this.btnEntrenar.setEnabled(true);
					this.btnVerMatriz.setEnabled(true);
				} catch (Exception ex) {
					System.out.println(ex);
				}
			}
		}

		else if (e.getSource().equals(this.btnGuardar)) {
			int returnVal = this.fc.showSaveDialog(this);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				try {
					String strFile = this.fc.getSelectedFile().getAbsolutePath();

					if (!strFile.endsWith(".robato")) {
						strFile += ".robato";
					}

					FileOutputStream fos = new FileOutputStream(new File(strFile));
					ObjectOutputStream out = new ObjectOutputStream(fos);
					out.writeObject(this.robots);
					out.writeObject(this.vectorParejas);
					out.flush();
					out.close();
				} 
				catch (Exception ex) {
					System.out.println(ex);
				}
			}
		}
	}
	
	
	public void update(Observable o, Object arg) {
		if(arg instanceof String){
			String message = (String)arg;
			if(message.equalsIgnoreCase("UPDATE") ){
				if(this.frameMatrices.isVisible()){
					synchronized (this.frameMatrices) {
						int index = this.comboBoxMatriz.getSelectedIndex() - 1;
						this.frameMatrices.printMatriz(index);
					}
				}
			}
			else
				this.textArea.append((String)arg);
		}
		
		else if(arg instanceof double[]){
			double point[] = (double[]) arg;
			this.grafico.addPoint(point[0], point[1]);
			this.grafico.update(this.grafico.getGraphics());
		}
		
		else if(arg instanceof Boolean ){
			boolean b = ((Boolean)arg).booleanValue();
			this.btnInit.setEnabled(true);
			this.btnPausa.setEnabled(false);
			
			if(b){				
				JOptionPane.showMessageDialog(this, "Entrenamiento terminado.", "RobAto", JOptionPane.INFORMATION_MESSAGE);
			}
			else if(!b){
				JOptionPane.showMessageDialog(this, "Limite de Iteraciones Alcanzado. Fin entrenamiento", "RobAto", JOptionPane.WARNING_MESSAGE );
			}
		}
	}
	
	public static void main(String deflt[]) {
		GUIRobots gui = new GUIRobots();
		RefineryUtilities.centerFrameOnScreen(gui);
		gui.setVisible(true);
	}
}